﻿using System;
using System.Activities;
using System.Activities.Presentation;
using System.Activities.Presentation.Model;
using System.Activities.Presentation.Services;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Vision.VisionWorkshop.Controls
{    
    class TypeDataSource
    {
        public static IList<TypeInfo> GenerateTypeInfoList(WorkflowDesigner wd)
        {
            List<TypeInfo> TypeInfoList = new List<TypeInfo>();

            var ms = wd.Context.Services.GetService<ModelService>();

            IEnumerable<ModelItem> ArgumentCollection = ms.Find(ms.Root, typeof(DynamicActivityProperty));
            TypeInfoList.AddRange(AddItemsToList(ArgumentCollection));

            IEnumerable<ModelItem> VariableCollection = ms.Find(ms.Root, typeof(Variable));
            TypeInfoList.AddRange(AddItemsToList(VariableCollection));

            TypeInfoList.Sort();
            return TypeInfoList;
        }

        private static IList<TypeInfo> AddItemsToList(IEnumerable<ModelItem> Items)
        {
            List<TypeInfo> TypeInfoList = new List<TypeInfo>();

            foreach (var item in Items)
            {
                string ItemName = item.Properties.Find("Name").Value.ToString();
                string ItemTypeName = item.Properties.Find("Type").Value.ToString();

                string pattern = Regex.Escape("[") + "(.*?)" + Regex.Escape("]");
                Match m = Regex.Match(ItemTypeName, pattern, RegexOptions.None);
                if (m.Success)
                {
                    ItemTypeName = m.Groups[1].Value;
                }

                Type ItemType = Type.GetType(ItemTypeName, false);

                if (ItemType == null)
                {
                    var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                    foreach (var assembly in assemblies)
                    {
                        ItemType = assembly.GetType(ItemTypeName, false);
                        if (ItemType != null)
                        {
                            break;
                        }
                    }
                }
                if (ItemType != null)
                {
                    TypeInfoList.Add(AddTypeToList(ItemName, ItemType));
                }
            }
            return TypeInfoList;
        }

        private static TypeInfo AddTypeToList(string ItemName, Type ItemType)
        {
            var TypeInfoItem = new TypeInfo()
            {
                MemberName = ItemName,
                TypeName = ItemType.Name,
            };

            List<TypeInfo> Children = new List<TypeInfo>();
            foreach (var member in ItemType.GetProperties())
            {
                if (member.MemberType == System.Reflection.MemberTypes.Property)
                {
                    if (ItemType != member.PropertyType)
                    {
                        Children.Add(AddTypeToList(member.Name, member.PropertyType));
                    }
                }
                else
                {
                    Children.Add(AddTypeToList(member.Name, member.GetType()));
                }
            }

            if (Children.Count > 0)
            {
                Children.Sort();
                TypeInfoItem.Children = Children;
            }
            return TypeInfoItem;
        }
    }
}
